<?php

namespace App\Models;

use App\Enums\MemberBalanceType;
use App\Enums\OrderFrom;
use App\Enums\OrderItemType;
use App\Enums\OrderType;
use App\Enums\PayChannel;
use App\Enums\TableStatus;
use App\Enums\TradeStatus;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;

class Order extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'order_no', 'user_id', 'member_id', 'store_id', 'status',
        'money', 'discount_money', 'origin_money', 'pay_channel', 'handover', 'comment',
        'type', 'from', 'pay_at', 'give_money', 'member_balance_type', 'give_table_money',
        'miniapp_member_recharge_option_id',
    ];

    protected $casts = [
        'pay_at' => 'datetime',
        'type' => OrderType::class,
        'from' => OrderFrom::class,
        'status' => TradeStatus::class,
        'member_balance_type' => MemberBalanceType::class,
    ];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function member()
    {
        return $this->belongsTo(Member::class);
    }

    public function store()
    {
        return $this->belongsTo(Store::class);
    }

    public function items()
    {
        return $this->hasMany(OrderItem::class);
    }

    public function miniappMemberRechargeOption()
    {
        return $this->belongsTo(MiniappMemberRechargeOption::class);
    }

    public static function generateOrderNo()
    {
        return 'TQ-'.time().rand(10000, 99999);
    }

    public function sumMoney()
    {
        $this->money = $this->items()->sum('money');
        $this->discount_money = $this->items()->sum('discount_money');
        $this->origin_money = $this->items()->sum('origin_money');
    }

    /**
     * @return OrderItem|null
     */
    public function getTableItem()
    {
        return $this->items()->where('type', OrderItemType::Table)->first();
    }

    public static function createEmptyOrder(User $postUser, Member|null $member = null) : Order
    {
        $order = Order::create([
            'order_no' => Order::generateOrderNo(),
            'user_id' => $postUser->id,
            'member_id' => $member?->id,
            'store_id' => $postUser->store_id,
            'status' => TradeStatus::Created,
            'money' => 0,
            'discount_money' => 0,
            'origin_money' => 0,
            'handover' => 0,
            'comment' => '',
            'type' => OrderType::Counter,
            'from' => OrderFrom::Counter,
        ]);

        return $order;
    }

    public static function createVirtualTableOrder(User $postUser, Table $table, Member|null $member = null) : Order
    {
        DB::transaction(function () use ($postUser, $table, $member, &$order) {

            /**
             * @var Order $order
             */
            $order = Order::create([
                'order_no' => Order::generateOrderNo(),
                'user_id' => $postUser->id,
                'member_id' => $member?->id,
                'store_id' => $postUser->store_id,
                'status' => TradeStatus::Created,
                'money' => 0,
                'discount_money' => 0,
                'origin_money' => 0,
                'handover' => 0,
                'comment' => '',
                'type' => OrderType::Counter,
                'from' => OrderFrom::Counter,
            ]);

            //创建item
            $order->items()->create([
                'count' => 1,
                'money' => 0,
                'discount_money' => 0,
                'origin_money' => 0,
                'type' => OrderItemType::Table,
                'cost_rule_id' => 0,
                'table_id' => $table->id,
                'start_at' => now(),
                'is_virtual' => true,
            ]);

            //锁定球桌
            $table->status = \App\Enums\TableStatus::InnerVirtual->value;
            $table->use_start_at = date('Y-m-d H:i:s');
            $table->table_order_id = $order->id;
            $table->save();
        });

        return $order;
    }

    public static function createTableOrder(User $postUser, Table $table, CostRule $costRule, Member|null $member = null) : Order
    {
        DB::transaction(function () use ($postUser, $table, $costRule, $member, &$order) {

            /**
             * @var Order $order
             */
            $order = Order::create([
                'order_no' => Order::generateOrderNo(),
                'user_id' => $postUser->id,
                'member_id' => $member?->id,
                'store_id' => $postUser->store_id,
                'status' => TradeStatus::Created,
                'money' => 0,
                'discount_money' => 0,
                'origin_money' => 0,
                'handover' => 0,
                'comment' => '',
                'type' => OrderType::Counter,
                'from' => OrderFrom::Counter,
            ]);

            //创建item
            $order->items()->create([
                'count' => 1,
                'money' => 0,
                'discount_money' => 0,
                'origin_money' => 0,
                'type' => OrderItemType::Table,
                'cost_rule_id' => $costRule->id,
                'table_id' => $table->id,
                'start_at' => now(),
            ]);

            //锁定球桌
            $table->status = \App\Enums\TableStatus::Used->value;
            $table->use_start_at = date('Y-m-d H:i:s');
            $table->table_order_id = $order->id;
            $table->save();
        });

        return $order;
    }

    public static function orderIdsPayed($orderIds, PayChannel $type)
    {
        DB::transaction(function () use ($orderIds, $type) {

            $orders = Order::whereIn('id', $orderIds)->get();

            /**
             * @var Order $order
             */
            foreach ($orders as $order) {

                if ($order->status->canDone())
                    $order->orderPayed($type);
            }
        });
    }

    public function orderPayed(PayChannel $channel)
    {
        DB::transaction(function () use ($channel) {

            $this->status = TradeStatus::Payed;
            $this->pay_channel = $channel;
            $this->pay_at = now();
            $this->save();

            if (!empty($this->member) && $channel != PayChannel::Bad) {

                /**
                 * @var Member $member
                 */
                $member = $this->member;
                if ($this->type == OrderType::MemberRecharge) {

                    //增加充值总金额
                    $member->all_recharge += $this->money;
                    if ($this->member_balance_type == MemberBalanceType::General) {
                        $member->recharge(MemberBalanceType::General, $this->money, $channel, $this->user, $this->store, '台费充值', $this->give_money);
                    }
                    if ($this->member_balance_type == MemberBalanceType::General && $this->give_table_money > 0) {
                        $member->recharge(MemberBalanceType::Table, $this->give_table_money, $channel, $this->user, $this->store, '赠送桌台金额', 0);
                    }
                    if ($this->member_balance_type == MemberBalanceType::Table) {
                        $member->recharge(MemberBalanceType::Table, $this->give_money, $channel, $this->user, $this->store, '台费充值', 0);
                    }
                } else {

                    //增加消费总金额
                    $member->all_consumption += $this->money;

                    foreach ($this->items as $item) {

                        if (!empty($item->table_order_sparring_id)) {

                            //增加助教消费总金额
                            $member->all_sparring_consumption += $item->price;
                        }
                    }

                    //TODO: 尤物星球判断
                    //TODO: 小程序商品判断
                }

                $member->save();
            }
        });

        return $this;
    }

    public function getTotalMoney($finishDate)
    {
        $totalMoney = $this->money;
        /**
         * @var OrderItem $item
         */
        foreach ($this->items as $item) {

            if (empty($item->end_at) && in_array($item->type, [OrderItemType::Table, OrderItemType::Assistant]))
                $totalMoney += $item->getTotalMoney($finishDate);
        }
        return $totalMoney;
    }

    /**
     * 暂停
     * @return void
     */
    public function pause()
    {
        DB::transaction(function () {

            foreach ($this->items as $item) {
                $item->pause();
            }
        });
    }

    /**
     * 取消暂停
     * @return void
     */
    public function unpause()
    {
        DB::transaction(function () {

            foreach ($this->items as $item) {
                $item->unpause();
            }
        });
    }
}
